<?php
/**
 * Created by PhpStorm.
 * User: dumbledore
 * Date: 2017/12/19
 * Time: 下午4:10
 */

defined('BASEPATH') or exit('No direct script access allowed');
require APPPATH . '/libraries/pay/WxPay.Api.php';
require APPPATH . '/libraries/pay/PayNotifyCallBack.php';

class WxpayOnline extends CI_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->database();
        $this->load->model('order_model');
        $this->load->model('store_model');
        $this->load->model('customer_model');
        $this->load->library('form_validation'); //加载表单验证类库
        $this->load->helper('json');
        $this->load->helper('common');
        $this->output->set_content_type('application/html;charset=utf-8');
    }

    /**
     * @SWG\Post(
     *     summary="微信支付",
     *     path="/wxpay",
     *     tags={"客户端"},
     *     operationId="8",
     *     produces={"application/xml", "application/json"},
     *     @SWG\Parameter(
     *         description="用户身份秘钥",
     *         in="formData",
     *         name="session_key",
     *         required=true,
     *         type="string",
     *     ),
     *     @SWG\Parameter(
     *         description="店铺id",
     *         in="formData",
     *         name="shop_id",
     *         required=true,
     *         type="integer",
     *     ),
     *     @SWG\Parameter(
     *         description="商品信息(json格式)",
     *         in="formData",
     *         name="detail",
     *         required=true,
     *         type="string",
     *     ),
     *     @SWG\Parameter(
     *         description="订单金额",
     *         in="formData",
     *         name="money",
     *         required=true,
     *         type="number",
     *     ),
     *     @SWG\Parameter(
     *         description="open_id",
     *         in="formData",
     *         name="open_id",
     *         required=true,
     *         type="string",
     *     ),
     *     @SWG\Response(
     *         response=200,
     *         description="成功",
     *     ),
     *     @SWG\Response(
     *         response="401",
     *         description="参数不全",
     *     ),
     * )
     */
    public function index()
    {
        $post = $this->input->post();
        if ($post['session_key'] && $post['order_bn'] && $post['open_id']) {

			$orders  = $this->db->where(array('a.order_bn' => $post['order_bn']))->select('a.*')->from('app_order a')
				->get()->row_array();
            if ($orders) {
                if (!$orders['money'] || $orders['money'] == 0) {
                    send_json(array('code' => 4004, 'data' => '', 'msg' => "请先计算订单价格"));
                }
                $order_bn = $orders['order_bn'];
                $open_id  = $post['open_id'];
                $fee      = $orders['money'] * 100;
            } else {
                send_json(array('code' => 4004, 'data' => '', 'msg' => "创建失败"));
            }
        } else {
            send_json(array('code' => 4000, 'data' => '', 'msg' => "缺少参数"));
        }

        //         初始化值对象
        $input = new WxPayUnifiedOrder();
        //         文档提及的参数规范：商家名称-销售商品类目
        $input->SetBody("stack");
        //         订单号应该是由小程序端传给服务端的，在用户下单时即生成，demo中取值是一个生成的时间戳
        $input->SetOut_trade_no($order_bn);
        //         费用应该是由小程序端传给服务端的，在用户下单时告知服务端应付金额，demo中取值是1，即1分钱
        $input->SetTotal_fee($fee);
        $input->SetNotify_url($this->config->item('base_url') . "/wxpay/notify"); //需要自己写的notify.php\
        $input->SetTrade_type("JSAPI");
        //         由小程序端传给后端或者后端自己获取，写自己获取到的，
        $input->SetOpenid($open_id);
        //        $input->SetOpenid($this->getSession()->openid);
        //         向微信统一下单，并返回order，它是一个array数组
        $order = WxPayApi::unifiedOrder($input);
        //         json化返回给小程序端
        header("Content-Type: application/json");
        return $this->getJsApiParameters($order, $orders['id']);
    }

    private function getJsApiParameters($UnifiedOrderResult, $order_id)
    {

        //判断是否统一下单返回了prepay_id
        if (!array_key_exists("appid", $UnifiedOrderResult)
            || !array_key_exists("prepay_id", $UnifiedOrderResult)
            || $UnifiedOrderResult['prepay_id'] == "") {
            send_json(array('code' => -1, 'data' => $UnifiedOrderResult, 'msg' => "fail"));
            throw new WxPayException("参数错误");
        }

        $jsapi = new WxPayJsApiPay();
        $jsapi->SetAppid($UnifiedOrderResult["appid"]);
        $timeStamp = time();
        $jsapi->SetTimeStamp("$timeStamp");
        $jsapi->SetNonceStr(WxPayApi::getNonceStr());
        $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
        $jsapi->SetSignType("MD5");
        $jsapi->SetPaySign($jsapi->MakeSign());
        $parameters             = $jsapi->GetValues();
        $parameters['order_id'] = $order_id;
        send_json(array('code' => 2000, 'data' => array('data' => $parameters), 'msg' => "success"));
    }
    //这里是服务器端获取openid的函数
    private function getSession()
    {
        $code     = $this->input->post('code');
        $url      = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . WxPayConfig::APPID . '&secret=' . WxPayConfig::APPSECRET . '&js_code=' . $code . '&grant_type=authorization_code';
        $response = json_decode(file_get_contents($url));
        return $response;
    }

    // 回调函数
    public function notify()
    {
        $notify = new PayNotifyCallBack();
        $notify->Handle(false);
        $now          = date("Y-m-d H:i:s");
        $returnValues = $notify->GetValues();
        log_message('error', $now . '发生回调:' . json_encode($returnValues));
        //交易成功
        if (!empty($returnValues['return_code']) && $returnValues['return_code'] == 'SUCCESS') {
            // 解析xml
            libxml_disable_entity_loader(true);
            $postStr = $this->postdata(); //接收post数据
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $arr     = $this->object2array($postObj); //对象转成数组
            log_message('error', $now . ' 支付完成，返回值:' . json_encode($arr));

            //商户逻辑处理，如订单状态更新为已支付
            $order_bn       = $arr['out_trade_no'];
            $transaction_id = $arr['transaction_id'];
            // 判断流水号来源
            $where = array('a.order_bn' => $order_bn);
            $info  = $this->db->where($where)->select('a.*')->from('app_order a')
                ->get()->row_array();
            if ($info) {
                $this->db->where(array("order_bn" => $order_bn))->update('app_order', array('status' => 10, 'transaction_id' => $transaction_id,  'payment_at' => $now));
            }
        }

        echo $notify->ToXml(); //返回给微信确认
        //        $res = $notify->Queryorder('');
        //        send_json(array('code'=>0,'data'=>$res,'msg'=>"test"));
    }

    // 接收post数据
    /*
     *  微信是用$GLOBALS['HTTP_RAW_POST_DATA'];这个函数接收post数据的
     */
    public function postdata()
    {
        $receipt = $_REQUEST;
        if ($receipt == null) {
            $receipt = file_get_contents("php://input");
            if ($receipt == null) {
                $receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
            }
        }
        return $receipt;
    }

    //把对象转成数组
    public function object2array($array)
    {
        if (is_object($array)) {
            $array = (array) $array;
        }if (is_array($array)) {
            foreach ($array as $key => $value) {
                $array[$key] = $this->object2array($value);
            }
        }
        return $array;
    }

}
